<?php

namespace console\controllers;

use Yii;
use yii\console\Controller;

class BackupController extends Controller {
    
    public $type;
    private $db;
    
    public function __construct($id, $module, $config = array()) {
        parent::__construct($id, $module, $config);
        $this->db= Yii::$app->db;
    }

    public function options($actionID)
    {
        return ['type'];
    }
    
    public function optionAliases()
    {
        return ['t' => 'type'];
    }
    
    public function actionIndex()
    {
        $tables = $this->getTables();
        $tableSqls = $this->getTableSqls($tables);
        $dataSqls = $this->getDataSqls($tables);
        $sqls = array_merge($tableSqls, $dataSqls);
        switch ($this->type){
            case 'sql':
                $this->saveSql($sqls);
                break;
            case 'migrate':
                $this->saveMigrate($sqls);
                break;
            default :
                $this->saveSql($sqls);
                $this->saveMigrate($sqls);
                break;
        }
    }
    
    
    
    private function getTables(){
        $sql = 'SHOW TABLES';
        $data = $this->db->createCommand($sql)->queryAll();
        $tables = [];
        $s = explode(';', $this->db->dsn);
        $dbname = str_replace('dbname=', '', $s[1]);
        foreach((array)$data as $k => $v){
            $tables[] = $v['Tables_in_'.$dbname];
        }
        return $tables;
    }
    
    private function getTableSqls($tables){
        $sqls = [];
        foreach((array)$tables as $k => $table){
            $t = str_replace($this->db->tablePrefix, '', $table);
            if(!in_array($t, ['migration', 'users'])){
                $sqls[$table] = $this->getTableCreateSql($table);
            }
        }
        return $sqls;
    }
    
    private function getTableCreateSql($table){
        $sql = 'SHOW CREATE TABLE `'.$table.'`';
        $data = $this->db->createCommand($sql)->queryOne();
        return $data['Create Table'];
    }


    private function getDataSqls($tables){
        //读取表字段列表
        //读取表数据列表
        //循环生产SQL语句
        $sqls = [];
        foreach((array)$tables as $k => $table){
            $t = str_replace($this->db->tablePrefix, '', $table);
            if(!in_array($t, ['migration', 'users'])){
                $sql = $this->getRowSql($table);
                if(!empty($sql)){
                    $s = $this->getRowSql($table);
                    foreach((array)$s as $key => $v){
                        $sqls[$table.'|data|'.$key] = $v;
                    }
    //                $sqls[$table.'|data'] = $this->getRowSql($table);
                }
            }
        }
        return $sqls;
    }
    
    private function getRowSql($table){
        $fields = $this->getFields($table);
        $data = $this->getTableData($table);
        $str = 'INSERT INTO `'.$table.'` (`'.implode('`,`', $fields).'`) VALUES ';
        $sqls = [];
        foreach((array)$data as $key => $d){
            foreach((array)$d as $a => $b){
                $b = str_replace('\'', '', $b);
                $d[$a] = $b;
            }
            $midstr = implode('\',\'', $d);
            $midstr = str_replace('"', '\"', $midstr);
            //$midstr = str_replace("'", "\'", $midstr);
            $midstr = str_replace('$', '\$', $midstr);
            $sqls[] = '(\''.$midstr.'\')';
        }
        if(empty($sqls)){return false;}
        $sql = $this->getSqls($sqls, $str, $table);
        return $sql;
    }
    
    private function getSqls($sqls, $str, $table = ''){
        $len = count($sqls);
        $dlen = 100;
        if(in_array($table, ['product_description', 'oc_product_description'])){
            $dlen = 2;
        }
        if(in_array($table, ['goods', 'information_description','oc_information_description'])){
            $dlen = 10;
        }
        echo $dlen.' | ';
        $c = ceil($len/$dlen);
        $sql = $s = [];
        if($len > $dlen){
            for($i = 0; $i < $c; $i++){
                $offset = $i * $dlen;
                $s = array_slice($sqls, $offset, $dlen);
                $sql[] = $str.implode(',', $s).';';
            }
        }else{
            $sql[] = $str.implode(',', $sqls).';';
        }
        return $sql;
    }


//    private function getSqlSize($sqls){
//        $sql = implode(',', $sqls);
//        return strlen($sql) / 1024 / 1024;
//    }


    private function getTableData($table){
        $sql = 'SELECT * FROM `'.$table.'`';
        $result = $this->db->createCommand($sql)->queryAll();
        return $result;
    }


    private function getFields($table){
        $sql = 'DESC `'.$table.'`';
        $result = $this->db->createCommand($sql)->queryAll();
        $fields = [];
        foreach((array)$result as $k => $v){
            $fields[] = $v['Field'];
        }
        return $fields;
    }


    private function saveSql($sqls){
        
    }
    
    private function saveMigrate($sqls){
        $path = str_replace('controllers', 'migrations', __DIR__);
        foreach($sqls as $table => $sql){
            $tabs = explode('|', $table);
            if(count($tabs) > 1){
                $this->setDataFile($tabs[0], $sql, $path, $tabs[2]);
            }else{
                $this->setTableFile($table, $sql, $path);
            }
        }
    }
    
    private function setDataFile($table, $sql, $path, $ord){
        $mrand = rand(100000, 999999);
        $dat = date('Ymd');
        $t = str_replace($this->db->tablePrefix, '', $table);
        $file = 'm' . gmdate('ymd_His') . '_' . $t.'_insert_data_'.$ord;
        $p = $path.'/'.$file.'.php';
        $str = str_replace('`'.$table.'`', '{{%'.$t.'}}', $sql);
        $content = $this->getFileContent($str, $t, $file, 'data');
        $result = @file_put_contents($p, $content);
    }


    private function setTableFile($table, $sql, $path){
        $mrand = rand(100000, 999999);
        $dat = date('Ymd');
        $t = str_replace($this->db->tablePrefix, '', $table);
        $file = 'm' . gmdate('ymd_His') . '_' . $t;
        $p = $path.'/'.$file.'.php';
        $str = str_replace('`'.$table.'`', '{{%'.$t.'}}', $sql);
        $content = $this->getFileContent($str, $t, $file);
        $result = @file_put_contents($p, $content);
    }


    private function getFileContent($sql, $table, $className, $type = 'table'){
        if($type == 'table'){
            $downCode = '$this->execute("DROP TABLE {{%'.$table.'}}");';
        }elseif($type == 'data'){
            $downCode = '$this->execute("TRUNCATE {{%'.$table.'}}");';
        }
        $str = '<?php

use yii\db\Migration;

class '.$className.' extends Migration
{
    public function up()
    {
        $sql = "'.$sql.'";
        $this->execute($sql);
    }

    public function down()
    {
        '.$downCode.'
    }
}
';
        return $str;
    }
}